package com.bbh.plugin.single.privilege.demo.client;

import com.bbh.common.domain.Condition;
import com.bbh.common.domain.Menu;
import com.bbh.common.domain.MenuResult;
import com.bbh.common.domain.Order;

import com.bbh.plugin.single.privilege.core.entity.Account;
import com.bbh.plugin.single.privilege.core.entity.Resource;
import com.bbh.plugin.single.privilege.core.entity.Role;
import com.bbh.plugin.single.privilege.core.entity.Rule;
import com.bbh.plugin.single.privilege.core.enums.BaseEnum;
import com.bbh.plugin.single.privilege.core.service.*;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.config.shiro.base.entity.ShiroAccount;
import org.springframework.boot.config.shiro.base.entity.ShiroResource;
import org.springframework.boot.config.shiro.base.entity.ShiroRole;
import org.springframework.boot.config.shiro.base.entity.ShiroRule;
import org.springframework.boot.config.shiro.base.service.ShiroAccountService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by roman_000 on 2015/10/3.
 */
@Service
@Transactional(readOnly = true)
public class ShiroAccountServiceImpl implements ShiroAccountService {
    private static final Logger log = LoggerFactory.getLogger(ShiroAccountServiceImpl.class);

    @Autowired
    private ResourceService resourceService;
    @Autowired
    private RoleService roleService;
    @Autowired
    private AccountAppService accountAppService;
    @Autowired
    private RuleService ruleService;
    @Value("${system.appKey}")
    private String sys_code;
    @Autowired
    private AccountService accountService;

    @Override
    public ShiroAccount findByLoginName(String loginName) {
        Account params = new Account();
        params.setLoginName(loginName);
        Account account = accountService.selectOne(params);
        //转换成ShiroAccount
        return RbacHelper.convert2ShiroAccount(account);
    }


    @Override
    @Transactional(readOnly = false)
    public void updateShiroAccount(ShiroAccount shiroAccount) {
        Account params = new Account();
        params.setLoginName(shiroAccount.getLoginName());
        Account account = accountService.selectOne(params);
        //判断该账号是不是可登陆当前系统
        List<String> accountAppCodeList = accountAppService.findAccountAppCodeList(account.getId());
        if (CollectionUtils.isEmpty(accountAppCodeList) || !accountAppCodeList.contains(sys_code)) {
            log.debug("账号没有授权登陆..." + sys_code);
            account = null;
        }
        if (account != null) {
            account.setLoginFailureCount(shiroAccount.getLoginFailureCount());
            account.setIsLocked(shiroAccount.getIsLocked());
            account.setLockedTime(shiroAccount.getLockedTime());
            accountService.updateByPrimaryKey(account);
        }
    }

    @Override
    public List<ShiroResource> findAllShiroResourceByAppKey() {
        Condition condition = new Condition();
        condition.put("appKey", Condition.EQ, sys_code);
        condition.put("dataStatus", Condition.EQ, BaseEnum.DATA_STATUS.NORMAL.getKey());
        List<Resource> resourceList = resourceService.selectList(condition, Lists.newArrayList(new Order("sort", Order.ASC)));
        return RbacHelper.convert2ShiroResourceList(resourceList);
    }


    @Override
    public MenuResult findMenuListByLoginName( String loginName) {
        if (StringUtils.isNotBlank(loginName)) {
            return resourceService.findMenuListByLoginName(loginName,sys_code);
        }
       return  null;
    }

    @Override
    public List<ShiroRule> findRuleListByLoginName(String loginName) {
        List<Rule> ruleList = ruleService.findRuleListByLoginName(sys_code, loginName);
        List<ShiroRule> shiroRuleList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(ruleList)) {
            ShiroRule shiroRule;
            for (Rule rule : ruleList) {
                shiroRule = new ShiroRule();
                BeanUtils.copyProperties(rule, shiroRule);
                shiroRuleList.add(shiroRule);
            }
        }
        return shiroRuleList;
    }

    @Override
    public List<ShiroRole> findShiroRoleListByLoginName( String loginName) {
        List<ShiroRole> shiroRoleList = Lists.newArrayList();
        ShiroRole shiroRole;
        List<Role> roleList = roleService.findRoleListByLoginName(sys_code, loginName);
        if (CollectionUtils.isNotEmpty(roleList)) {
            for (Role role : roleList) {
                shiroRole = new ShiroRole();
                shiroRole.setCode(role.getEnname());
                shiroRole.setName(role.getName());
                shiroRole.setShiroResourceList(this.findShiroResourceByRoleId(sys_code, role.getId()));
                shiroRoleList.add(shiroRole);
            }
        }
        return shiroRoleList;
    }

    /**
     * 通过角色Id查询资源
     *
     * @return
     */
    private List<ShiroResource> findShiroResourceByRoleId(String appKey, Serializable roleId) {
        Condition condition = new Condition();
        condition.put("appKey", appKey);
        condition.put("roleId", roleId);
        List<Resource> resourceList = resourceService.findResourceListByRoleId(condition);
        return RbacHelper.convert2ShiroResourceList(resourceList);
    }

    /**
     * 菜单根据parentId转换
     *
     * @return
     */
    private Map<String, Object> getMenuMap(Menu<Resource> menuList) {
        log.debug("菜单资源开始......");
        Map<String, Object> resultMap = Maps.newHashMap();
//        ShiroResource shiroResource;
//        if (CollectionUtils.isNotEmpty(menuList.getResourceList())) {
//            List<ShiroResource> shiroResourceResultList = null;
//            for (Resource resource : menuList.getResourceList()) {
//                shiroResourceResultList = (List<ShiroResource>) resultMap.get(resource.getParentId());
//                if (CollectionUtils.isEmpty(shiroResourceResultList)) {
//                    shiroResourceResultList = Lists.newArrayList();
//                }
//                shiroResource = RbacHelper.convert2ShiroResource(resource);
//                log.debug(shiroResource.getId() + ":" + shiroResource.getName());
//                shiroResourceResultList.add(shiroResource);
//                resultMap.put(resource.getParentId(), shiroResourceResultList);
//            }
//        }
//        resultMap.put("rootId", menuList.getRootId());
//        resultMap.put("rootId", menuList.getRootId());
//        log.debug("rootId:" + menuList.getRootId());
//        log.debug("菜单资源结束......");
        return resultMap;
    }
}
